#!/usr/bin python
import gammu
from logovani import gsmLogger
from nacteniKonfigurace import smsNumbersWhiteList, cisloProZaslaniChybovychSMS
from nacteniKonfigurace import smsNumbersIgnoredList
from nacteniKonfigurace import adresaProOvereniVPN, adresaProOvereniPPP, semaforPrenesDataCentrala, semaforPrenesDataTelem, razitkoGSMZije
from nacteniKonfigurace import pidGsmRobot, pozadavekChciProvest, silaSignaluGSM
from nacteniKonfigurace import pozadavekNaRestartGSM
from nacteniKonfigurace import razitkoPrenosZahajenCentrala, razitkoPrenosZahajenTelem, periodaOpakovaniPrenosu, pocetOpakovaniDoResetuModemu, pocetOpakovaniPrenosuCentrala, pocetOpakovaniPrenosuTelem
from nacteniKonfigurace import semaforPrihlasenTechnik
from nacteniKonfigurace import razitkoHsoRestart 
from bz2_gprs_ftp import *
from tabulky import SmsProOdeslani, UdalostiAutomatu
from sqlobject import *
from sqlobject.sqlbuilder import *

import ftplib, sys, os, stat, commands
import socket
import time
import tarfile
from sqlobject.util.csvexport import export_csv
import subprocess
import shutil
import traceback
import re
import random

from podpurneFunkce import _zjistiCisloAutomatu, vytvorSoubor

pid = str(os.getpid())
vytvorSoubor(pidGsmRobot, obsahSouboru=pid)

SmsProOdeslani.createTable(ifNotExists=True) # kdyz by spousteci skripty nevytvorily tabulku, vytvorime si ji sami
autorizovanaCisla = smsNumbersWhiteList.replace(' ', '').split(',')
ignorovanaCisla = smsNumbersIgnoredList.replace(' ', '').split(',')
sm = gammu.StateMachine()
sm.ReadConfig()
spojeni = GprsKomunikace()

class SMS(object):
    def __init__(self):
        # slovnik funkci je malymi pismeny, aby se eliminovaly mozne preklepy pri psani SMS
        self.slovnikFunkci = {'startvpn':self.startVPN, 
                               'restart':self.vzdalenyRestart, 
                        'nouzovyrestart':self.vzdalenyRestartNouzovy, 
                            'prenesdata':self.prenesDataObsluhaSms,
                            'prenesvsechnadata':self.prenesVsechnaDataObsluhaSms, 
                            #'cisloautomatu':self.zapisCisloAutomatu, 
                            'sms':self.posliToDal,
                            'halt':self.provedHalt
                            }
                            
        self.seznamFunkciProKtereJeNutneUkoncitGSM = ('startvpn', 'prenesdata', 'aktualizujdatabazi', 'prenesvsechnadata')
        self.vpnBylaNahozena = False
        self.telCisloZeKterehoBylaNahozenaVpn = False
        text = 'start skriptu gsm_robot'
        gsmLogger.info(text)
        print text
        self.IMEI = ""
        self.IMSI = ""
        self.gammuNeniSpusteno = True
        self.cRandom = random.randint(50,150) # (cislo/10) * 60 sekund -> 5-15 minut
        
    def refreshRazitkaGSMZije(self):
        # vytvori prazdny soubor razitkoGSMZije do RAMdisku, z timestampu tohoto souboru muzeme zjistit, zda automat "zije"
        vytvorSoubor(razitkoGSMZije)        
        
    def _gammuKomunikaceNavazana(self):
        if spojeni.pidBezicihoGPRS:
            gsmLogger.info('na seriovem portu probiha komunikace ppp/GPRS')
            gsmLogger.info('z tohoto duvodu nelze na stejnem portu navazat komunikaci s USB modemem')
            time.sleep(5) # asi nekdo koumunikuje (vpn??), tak abysme do toho nebusili jak hluchej do vrat
            return "gprs"
        try:
            if self.gammuNeniSpusteno:
                sm.Init()
                self.gammuNeniSpusteno = False
                gsmLogger.info('podarilo se iniciovat seriovou komunikaci s USB modemem')                
                if not self.IMEI or not self.IMSI:
                    self.IMSI = sm.GetSIMIMSI()[:15]
                    self.IMEI = sm.GetIMEI()[:15]
                return "gammu"
            else:
                self.ukonciGammu()
#            except (gammu.ERR_TIMEOUT, gammu.ERR_DEVICEOPENERROR, gammu.ERR_DEVICENOTEXIST), why:
        except Exception, why:
            text = "iniciace Gammu nebyla uspesna: %s " % why                
            print text
            gsmLogger.error(text)
            self.ukonciGammu()                        
    gammuKomunikaceNavazana = property(_gammuKomunikaceNavazana)

    def ukonciGammu(self):
        text = "pokusime se o ukonceni seriove komunikace s USB modemem"
        print text
        gsmLogger.info(text)
        try:            
            sm.Terminate()            
            text = "sm.Terminate byl uspesne vykonan, seriova komunikace s USB modemem byla ukoncena"
            print text
            gsmLogger.info(text)                        
            self.gammuNeniSpusteno = True
#        except gammu.ERR_UNKNOWN, why:
        except Exception, why:
            text = 'nepodarilo se sm.Terminate(); %s' % why
            print text
            gsmLogger.error(text)
            self.restartGSM()
            
    def restartGSM(self):        
        #idAutomatu = CommandsAndStatus.get(1).idAutomatu
        #aktualnePrihlaseneId = CommandsAndStatus.get(1).aktualnePrihlaseneId
        if os.path.exists(semaforPrihlasenTechnik):
            text = "prihlasen technik, ukoncime GSM robot, nebudeme vypinat USB Vcc - odpojili bychom USB klavesnici"
            print text
            gsmLogger.debug(text)        
            sys.exit()
        text = "pozadujeme restart GSM, USB Vcc off/on"
        print text
        gsmLogger.error(text)
        vytvorSoubor(pozadavekNaRestartGSM)
        sys.exit()

#    def vytvorSoubor(self, soubor, obsahSouboru = None):
#        f = open(soubor, "w")
#        if obsahSouboru:
#            f.write(obsahSouboru)  
#        f.close()
        
    def vzdalenyRestart(self):        
        vytvorSoubor(soubor=pozadavekChciProvest, obsahSouboru = 'vzdalenyRestart')
    
    def vzdalenyRestartNouzovy(self):
        vytvorSoubor(soubor=pozadavekChciProvest, obsahSouboru = 'vzdalenyRestartNouzovy')

    def provedHalt(self):        
        print "Halt-podrizl jsem si vetev"        
        subprocess.call(["halt &"],shell=True)
        time.sleep(5)

    def mameNoveZpravyOdAutomatu(self,promazat):
        zpravy = ''
        seznamZpravDb = []
        zpravyOdAutomatu = SmsProOdeslani.select(SmsProOdeslani.q.odeslana==False, orderBy = ("id"))
        #print "DBG-hledani zprav v DB-rezim oznacovani ihned:",promazat
        for zprava in zpravyOdAutomatu:
            text = "SMS: %s" % zprava.textZpravy
            print text
            gsmLogger.info(text)
            zpravy+=zprava.textZpravy
            # PD - zde vlastne (historicky od Petra) rikame hop, i kdyz jsme jeste nepreskocili - cistejsi v situaci,
            #     kdy odeslani zpravy muze selhat a vest az k error 27 gammu a restartu gammu bude
            #     zde plnit seznam objektu zprav a po odeslani v odesliSMS dle nej flagovat... 
            #     Jinak ta vyjimka v takovem pripade (27) je gammu.ERR_UNKNOWN ... Super ciste by bylo samozrejme
            #     odesilat po jedne a rovnou flagovat, ale to by se muselo hodne predelat !
            if promazat:
                # rezim prvniho spusteni, zpravy od automatu nezpracovavame
                zprava.set(odeslana = True)
            else:
                # rezim "normalni", kdy se zpravy skutecne budou odesilat
                seznamZpravDb.append(zprava)
        self.zpravyOdAutomatu=zpravy
        self.seznamZpravDb=seznamZpravDb
        return self.zpravyOdAutomatu


    def odesliSMS(self, text='', cislo = cisloProZaslaniChybovychSMS):        
        # Kdyz se ma posilat chybova zprava a automat se zahoruje, tak se sms posle na testovaci cislo ...
        # Jednoduse by slo udelat, ze i napr. chyba uz na zacatku neinicializovaneho automatu (cislo automatu '00000000') se posle taky
        # testerovi, ale zatim to nebylo pozadovano, tester/monter by ji nejspis nevyresil ...
        # Chybne resi jednu situaci - ve stadiu zahorovani na povel od "chybare" odesle potvrzeni
        # testerovi. Povel provede, takze to prakticky nebude vadit.
        #if (cislo==cisloProZaslaniChybovychSMS) and (self._zjistiCisloAutomatu() in (cisloTestovacihoAutomatu)):
        #    cislo=cisloProZaslaniTestovacichSMS
        if self.telCisloZeKterehoBylaNahozenaVpn:
            cislo = self.telCisloZeKterehoBylaNahozenaVpn
            self.telCisloZeKterehoBylaNahozenaVpn = False
        if self.zpravyOdAutomatu:
            text+=self.zpravyOdAutomatu
        print "pozadavek na odeslani SMS:",  text
        '''sms umi na jeden zatah odeslat pouze 150 znaku, proto text musime rozdelit'''
        pocetEsemesek = len(text)//150
        for i in range(0, 1+pocetEsemesek):
            index1 = i*150 
            index2 = index1+150    
            odesilanyText = text[index1:index2]
            self._odesliSMS(odesilanyText, cislo)
            print cislo, odesilanyText
        # PD - promenna self.zpravyOdAutomatu se defakto maze (plni znova od prazdna) v _prectiZpravyOdAutomatu !
        for zprava in self.seznamZpravDb:
            zprava.set(odeslana=True)
        self.odeslaneZpravyVymazZDatabaze()
    
    def _odesliSMS(self, text, cislo):
        print "na cislo:", cislo, "odesilam text:", text
        gammuMessage = {'Text': text, 'SMSC': {'Location': 1}, 'Number': cislo}
        try:
            sm.SendSMS(gammuMessage)
            time.sleep(1)
        except (gammu.ERR_TIMEOUT,gammu.ERR_DEVICEOPENERROR), why:
            gsmLogger.critical('nepodarilo se odeslat sms')
            gsmLogger.critical(why)
    
    def odeslaneZpravyVymazZDatabaze(self):
        # Mazeme pouze vcerejsi a starsi, protoze denni historie zprav se pouziva pro detekci
        # opakovane dex chybove zpravu.
        dnesniDatum = time.strftime('%d.%m.%Y')
        odeslaneZpravy = SmsProOdeslani.select(AND(SmsProOdeslani.q.odeslana==True,
                                                   SmsProOdeslani.q.tStamp < dnesniDatum))
        for zprava in odeslaneZpravy:
            zprava.destroySelf()
        
    def nactiAndAnalyzujPrijateSMS(self):
        self.cisloZeKterehoBylaOdeslanaSMS = ""
        '''
        postupne z telefonu nacte vsechny prijate sms;
        vybere pouze posledni (nejmladsi) neprectenou zpravu, ktere byla odeslana z autorizovaneho cisla,
        kazdou zpravu po nacteni vymaze z telefonu        
        '''
        self.prijatyAutorizovanyPrikaz = set()
        try:
            sms = sm.GetNextSMS(Start = True, Folder = 0)     
            while 1:    
                for m in sms:
                    # vycisti pripadne neascii znaky
                    mText=m['Text'].encode('ascii','replace')
                    print m['Number'], mText, m['State'], m['Location']
                    print "autorizovana:", autorizovanaCisla
                    if m['Number'] in autorizovanaCisla and m['State'] == 'UnRead':                        
                        text = mText.lower()
                        print "klice:", self.slovnikFunkci.keys()
                        for klic in self.slovnikFunkci.keys():
                            if text.startswith(klic):
                                print "klic:", klic
                                self.cisloZeKterehoBylaOdeslanaSMS = m['Number']                                
                                self.prijatyAutorizovanyPrikaz = klic
                                self.celaPrijataSmsZprava = text
                    elif m['Number'] in ignorovanaCisla:
                        smsText = 'nasledujici zprava byla prijata z ignorovaneho cisla'
                        gsmLogger.warning(smsText)
                        UdalostiAutomatu(popisUdalosti= smsText, periferie = "SMS")
                        smsText = 'Number: %s; Text: %s' % (m['Number'], mText)
                        gsmLogger.warning(smsText)
                        UdalostiAutomatu(popisUdalosti= smsText, periferie = "SMS")
                        
                    elif m['Number'] not in autorizovanaCisla:
                        smsText = 'nasledujici zprava byla prijata z neautorizovaneho cisla'
                        gsmLogger.critical(smsText)
                        UdalostiAutomatu(popisUdalosti= smsText, periferie = "SMS")
                        smsText = 'Number: %s; Text: %s' % (m['Number'], mText)
                        gsmLogger.critical(smsText)
                        UdalostiAutomatu(popisUdalosti= smsText, periferie = "SMS")
                        
                    gsmLogger.info('z pameti telefonu byla vymazana zprava: Number: %s; Text: %s' % (m['Number'], mText))
                    sm.DeleteSMS(0, m['Location'])
                sms = sm.GetNextSMS(Location = sms[0]['Location'], Folder = 0)
        except (gammu.ERR_NOTSUPPORTED, gammu.ERR_TIMEOUT, gammu.ERR_UNKNOWNRESPONSE, 
                gammu.ERR_DEVICEOPENERROR, gammu.ERR_CORRUPTED), why:
            # zda se, ze tyto chyby neprerusi seriovou komunikaci s telefonem, tak je neresime, jen logujeme
            gsmLogger.error(why)
        except (gammu.ERR_EMPTY), why: 
             # v pripade, ze modem neobsahuje zadne prijate SMS, hlasi tuto chybu, neni treba logovat
            pass
        except Exception, why:
            print Exception, why
            gsmLogger.error(why)
        if self.prijatyAutorizovanyPrikaz:
            self.textZpetnehoPotvrzeni = "obdrzel jsem prikaz: %s, pokusim se jej provest" % self.prijatyAutorizovanyPrikaz            
            print self.textZpetnehoPotvrzeni
            return self.prijatyAutorizovanyPrikaz
    mamePrijatySmsPrikaz = property(nactiAndAnalyzujPrijateSMS)
            
    def _zjistiZdaJeProProvedeniNekterehoPrikazuNutnoUkoncitGSM(self):                
        if self.prijatyAutorizovanyPrikaz in self.seznamFunkciProKtereJeNutneUkoncitGSM:
            return True
    proProvedeniPrikazuJeNutneUkoncitGSM = property(_zjistiZdaJeProProvedeniNekterehoPrikazuNutnoUkoncitGSM)

    
    def provedPrijatyPrikaz(self):
        prikaz = self.prijatyAutorizovanyPrikaz
        try:
            text = 'POKUSIM SE PROVEST PRIJATY SMS PRIKAZ: %s' %  prikaz
            print text
            gsmLogger.info(text)
            self.slovnikFunkci[prikaz]()
        except Exception, why:
            text = "prijaty autorizovany prikaz %s se nepodarilo vykonat" % prikaz
            print text
            gsmLogger.critical(text)
            gsmLogger.critical(why)
        self.prijatyAutorizovanyPrikaz = ''
        
    def posliToDal(self):
        try:
            prikaz, cislo, text = self.celaPrijataSmsZprava.split(';')
            self._odesliSMS(text, cislo)
        except Exception, why:
            print why
            gsmLogger.critical(why)
            gsmLogger.critical(self.celaPrijataSmsZprava)
            self._odesliSMS(why, self.cisloZeKterehoBylaOdeslanaSMS)
            
            
#    def zapisCisloAutomatu(self):
#        '''
#        centralni pocitac na vyzadani prideli automatu cislo 
#        a to mu zasle prostrednictvim SMS ve tvaru: "cisloAutomatu:00000018"
#        cislo vystavime do RAMdisku
#        '''
#        text=self.celaPrijataSmsZprava.split(";")
#        cislo=text[1]
#        datumPlusCas = text[3]
#        vytvorSoubor(cisloAutomatu, obsahSouboru=cislo)
#        subprocess.call(["date -s '%s'" % datumPlusCas],shell=True)
#        subprocess.call(["hwclock --systohc --utc &"],shell=True)
        
    def prenesDataCentrala(self,provestExportDat=True,celeLogy=False):
        prenesDataCentrala(provestExportDat,celeLogy) # trosku zmatecne volani funkce bz2_gprs_ftp (from funkce bz2_gprs_ftp import *)

    def prenesDataTelem(self,provestExportDat=True,celeLogy=False):
        prenesDataTelem(provestExportDat,celeLogy) # trosku zmatecne volani funkce bz2_gprs_ftp (from funkce bz2_gprs_ftp import *)

    def prenesDataObsluhaSms(self):
        # pomocna metoda pro zavolani ze slovniku sms obsluznych funkci
        self.prenesDataTelem(provestExportDat=True,celeLogy=False)
        time.sleep(5)
        self.prenesDataCentrala(provestExportDat=True,celeLogy=False)

    def prenesVsechnaDataObsluhaSms(self):
        # pomocna metoda pro zavolani ze slovniku sms obsluznych funkci
        self.prenesDataTelem(provestExportDat=True,celeLogy=True)
        time.sleep(5)
        self.prenesDataCentrala(provestExportDat=True,celeLogy=True)

    def _zjistiZdaNekdoVydalPrikazPrenesData(self,semaforPrenesData):        
        if os.path.exists(semaforPrenesData):                        
            # PD - cAutomatu = int(_zjistiCisloAutomatu())
            # Cislo je prilis velke, nelze ho pouzit, pouzijeme randomizaci, cislo cca 50-150 ->
            # cRandom nastavime v initu (konstruktoru objektu). 
            timestampZacatekCekani = os.stat(semaforPrenesData).st_mtime
            pozadavekNaOdlozeniZacatkuPrenosuDat = self.cRandom/10.0 * 60 # o kolik sekund odlozime zahajeni prenosu dat (aby nesel prenos dat ze vsech automatu najednou)
            jizCekame = time.time() - timestampZacatekCekani
            if jizCekame > pozadavekNaOdlozeniZacatkuPrenosuDat:
            # PRENOSY CHCEME VZDY ODLOZENE - or os.path.exists(semaforPrihlasenTechnik):                 
                try:
                    #NE, to udela az skutecne zahajeny prenos dat ! os.remove(semaforPrenesData)
                    return True
                except Exception, why:
                    print why
                    gsmLogger.critical("zjistiZdaNekdoVydalPrikazPrenesData:" + why)                    
            else:
                text = "jizCekame(%s): %s, mame cekat: %s" % (semaforPrenesData, jizCekame, pozadavekNaOdlozeniZacatkuPrenosuDat)
                print text                
    existujeSemaforovyPrikazPrenesDataCentrala = property(fget = lambda self: self._zjistiZdaNekdoVydalPrikazPrenesData(semaforPrenesData=semaforPrenesDataCentrala))
    existujeSemaforovyPrikazPrenesDataTelem = property(fget = lambda self: self._zjistiZdaNekdoVydalPrikazPrenesData(semaforPrenesData=semaforPrenesDataTelem))

#    def _zjistiZdaExistujeInventuraAUplynulPozadovanyCas(self):
#        casNejmlInv=self.zjistiMtimeNejmladsiInventuryNeboCashboxuZAdresare(adresarPrenosDatProCentraluFTP)
#        if casNejmlInv:
#            # pokud byla inventura, vrati nenulovy udaj
#            jizCekame = time.time() - casNejmlInv
#            mameCekat = 15 * 60 # 15 minut, neni potreba mit v cfg file (puvodne bylo 30-PD)
#            if jizCekame > mameCekat:
#                if not os.path.exists(semaforPrenesData):
#                    # Novy semafor budeme vytvaret pouze, pokud jiz neexistuje !
#                    return True
#                else:
#                    return False
#            else:
#                text = "jizCekame(na prenos po inventure): %s, mame cekat: %s" % (jizCekame, mameCekat)
#                print text
#    existujeInventuraAUplynulPozadovanyCas = property(_zjistiZdaExistujeInventuraAUplynulPozadovanyCas)

#    def zjistiMtimeNejmladsiInventuryNeboCashboxuZAdresare(self,directory):
#        # vrati nulu, pokud nenajde zadny
#        files = [(os.stat(os.path.join(directory, file))[-2],file) for file in os.listdir(directory)]
#        files.sort(reverse=True)
#        for soubor in files:
#            pathFileName = os.path.join(directory, soubor[1])
#            if os.path.isfile(pathFileName):
#                if soubor[1].startswith("inventura_") or soubor[1].startswith("vycetka_"):
#                    return soubor[0]
#        return 0

    def _zjistiJestliSelhalMinulyPrenosAUplynulPozadovanyCas(self,razitkoPrenosZahajen,pocetOpakovaniPrenosu):        
        if os.path.exists(razitkoPrenosZahajen):            
            timestampZacatekCekani = os.stat(razitkoPrenosZahajen).st_mtime
            jizCekame = time.time() - timestampZacatekCekani
            if jizCekame > periodaOpakovaniPrenosu:
                novyPocet=self.nacteniPoctuOpakovaniPrenosu(pocetOpakovaniPrenosu)+1
                vytvorSoubor(pocetOpakovaniPrenosu,obsahSouboru=str(novyPocet))
                return True
            else:
                text = "jizCekame(po chybe prenosu %s): %s, mame cekat: %s" % (razitkoPrenosZahajen, jizCekame, periodaOpakovaniPrenosu)
                print text                
    selhalMinulyPrenosCentralaAUplynulPozadovanyCas = property(fget = lambda self: self._zjistiJestliSelhalMinulyPrenosAUplynulPozadovanyCas(razitkoPrenosZahajen=razitkoPrenosZahajenCentrala,pocetOpakovaniPrenosu=pocetOpakovaniPrenosuCentrala))
    selhalMinulyPrenosTelemAUplynulPozadovanyCas = property(fget = lambda self: self._zjistiJestliSelhalMinulyPrenosAUplynulPozadovanyCas(razitkoPrenosZahajen=razitkoPrenosZahajenTelem,pocetOpakovaniPrenosu=pocetOpakovaniPrenosuTelem))

    def nacteniPoctuOpakovaniPrenosu(self,pocetOpakovaniPrenosu):
        try:
            f=open(pocetOpakovaniPrenosu,'r')
            pocet=int(f.readline().rstrip())
            f.close()
        except Exception:
            pocet=0
        return pocet

    def kontrolaPoctuOpakovaniEvRestart(self,pocetOpakovaniPrenosu):
        if self.nacteniPoctuOpakovaniPrenosu(pocetOpakovaniPrenosu) >= pocetOpakovaniDoResetuModemu:
            text="prekrocen limit opakovani prenosu"
            print text
            gsmLogger.error(text)
            self.restartGSM()
    
    def startVPN(self):
        spojeni.startVPN()
        self.vpnBylaNahozena = True
        self.telCisloZeKterehoBylaNahozenaVpn = self.cisloZeKterehoBylaOdeslanaSMS
        
    def stopGPRS(self, text):
        print text
        gsmLogger.info(text)
        SmsProOdeslani(textZpravy = text)        
        self.vpnBylaNahozena = False
        spojeni.stopGPRS()
        
    def _zkusNacistIMSI(self):
        try:
            IMSI = sm.GetSIMIMSI() #kontrola, zda funguje komunikace s modemem        
            return IMSI
        except Exception, why:        
            text = "modem hlasi chybu pri pokusu o nacteni IMSI cisla SIM karty"            
            print text
            gsmLogger.error(text)
            gsmLogger.error(why)
    cisloIMSI = property(_zkusNacistIMSI)
    
    def zkontrolujZnaky(self, text):
        # Zkontroluje znaky, kdyz budou netistitelne, vrati None ...
        if not text:
            return None
        if re.match("^[-+ 0-9a-zA-Z]+$",text):
            return text
        else:
            return None
        
    def zjistiSiluSignalu(self):
        sila = "%s dB %s/%s" % (sm.GetSignalQuality()["SignalStrength"],
                                self.zkontrolujZnaky(sm.GetNetworkInfo()["CID"]),
                                self.zkontrolujZnaky(sm.GetNetworkInfo()["LAC"])
                               )
        f = open(silaSignaluGSM, "w")        
        f.write(sila)
        f.close
        print "Sila signalu a CID/LAC GSM: %s" % sila
        
if __name__ == '__main__':
    skriptBylPraveSpusten = True
    modem = SMS()
    casKdySeZnovuZeptameNaDoslouSMS = time.time()    
    while 1:
        try:
            nahozeniKomunikace=modem.gammuKomunikaceNavazana
            if (nahozeniKomunikace=="gammu") or (nahozeniKomunikace=="gprs"):
                modem.refreshRazitkaGSMZije()
                if os.path.exists(razitkoHsoRestart):
                    os.remove(razitkoHsoRestart)
            if nahozeniKomunikace=="gammu": 
                if skriptBylPraveSpusten: # pri prvnim pruchodu smyckou nacteme z modemu vsechny prijate SMS 
                                          # a zahodime je (kdyz skript nebezel, mohou byt v modemu prijaty napr. SMS od operatora)
                    skriptBylPraveSpusten = False
                    modem.mamePrijatySmsPrikaz
                    modem.mameNoveZpravyOdAutomatu(promazat=True) # zahodime take vsechny stare hlasky z automatu
                while 1:           
                    modem.refreshRazitkaGSMZije()
                    if modem.mameNoveZpravyOdAutomatu(promazat=False):
                        modem.odesliSMS()
                    now = time.time()
                    if casKdySeZnovuZeptameNaDoslouSMS < now:
                        if os.path.exists(semaforPrihlasenTechnik):
                            perioda = 5 # pokud technik prihlasen je, testujeme sms a silu signalu casteji
                        else:
                            perioda = 60*1 # znovu se zeptame za minutu, pokud neni prihlasen technik
                        casKdySeZnovuZeptameNaDoslouSMS = now + perioda 
                        if modem.mamePrijatySmsPrikaz:                            
                            if modem.prijatyAutorizovanyPrikaz not in ('cisloautomatu','sms'):
                            #Na nektere sms nebudeme odpovidat potvrzovaci zpravou (serveru, pripadne speciality ...)
                                text = modem.textZpetnehoPotvrzeni
                                cislo = modem.cisloZeKterehoBylaOdeslanaSMS
                                modem.odesliSMS(text=text, cislo=cislo)
                            if modem.proProvedeniPrikazuJeNutneUkoncitGSM:
                                modem.ukonciGammu()
                                modem.provedPrijatyPrikaz()
                                break # musime se dostat do casti smycky, kde se znovu nahazuje seriova GSM komunkace s modemem
                            else:
                                modem.provedPrijatyPrikaz()                        
                        modem.zjistiSiluSignalu()
                        if not modem.cisloIMSI:
                            modem.ukonciGammu()
                            break
                    #if modem.existujeInventuraAUplynulPozadovanyCas:
                    #    vytvorSoubor(semaforPrenesData)
                    if modem.existujeSemaforovyPrikazPrenesDataTelem:
                        modem.ukonciGammu()
                        modem.prenesDataTelem()
                        break # musime se dostat do casti smycky, kde se znovu nahazuje seriova GSM komunkace s modemem
                    if modem.existujeSemaforovyPrikazPrenesDataCentrala:
                        modem.ukonciGammu()
                        modem.prenesDataCentrala()
                        break # musime se dostat do casti smycky, kde se znovu nahazuje seriova GSM komunkace s modemem
                    if modem.selhalMinulyPrenosTelemAUplynulPozadovanyCas:
                        modem.ukonciGammu()
                        modem.prenesDataTelem(provestExportDat=False)
                        modem.kontrolaPoctuOpakovaniEvRestart(pocetOpakovaniPrenosuTelem)
                        break # musime se dostat do casti smycky, kde se znovu nahazuje seriova GSM komunkace s modemem
                    if modem.selhalMinulyPrenosCentralaAUplynulPozadovanyCas:
                        modem.ukonciGammu()
                        modem.prenesDataCentrala(provestExportDat=False)
                        modem.kontrolaPoctuOpakovaniEvRestart(pocetOpakovaniPrenosuCentrala)
                        break # musime se dostat do casti smycky, kde se znovu nahazuje seriova GSM komunkace s modemem
                    time.sleep(1)
            if modem.vpnBylaNahozena and (not spojeni.existujePidOvereneBeziciVPN):
                text = 'VPN prerusena, ukoncuji GPRS'
                modem.stopGPRS(text)
            #if modem.existujeInventuraAUplynulPozadovanyCas:
            #    vytvorSoubor(semaforPrenesData)
            if modem.existujeSemaforovyPrikazPrenesDataTelem:
                modem.prenesDataTelem()
            if modem.existujeSemaforovyPrikazPrenesDataCentrala:
                modem.prenesDataCentrala()
            if modem.selhalMinulyPrenosTelemAUplynulPozadovanyCas:
                modem.prenesDataTelem(provestExportDat=False)
                modem.kontrolaPoctuOpakovaniEvRestart(pocetOpakovaniPrenosuTelem)
            if modem.selhalMinulyPrenosCentralaAUplynulPozadovanyCas:
                modem.prenesDataCentrala(provestExportDat=False)
                modem.kontrolaPoctuOpakovaniEvRestart(pocetOpakovaniPrenosuCentrala)
            time.sleep(10)
        except Exception,  why:
            print why
            gsmLogger.info(why)
